home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 1.iso / dist / fw_exmh.idb / usr / freeware / lib / exmh-2.5 / glimpse.tcl.z / glimpse.tcl
Text File  |  2002-07-08  |  22KB  |  733 lines

  1. # $Header: /cvsroot/exmh/exmh/lib/glimpse.tcl,v 1.4 2000/11/17 22:55:10 welch Exp $
  2. #
  3. # link glimpse to exmh to provide full text searching within and
  4. # across folders faster but less thoroughly than pick
  5. #
  6. # Requirements: glimpse V1.0 or lator (V4.0B1 recommended)
  7. #        tk4.2 (maybe also tk3.6),  exmh-2.0 (maybe also exmh-1.6.9)
  8. #
  9. # by Tom Phelps (phelps@cs.berkeley.edu)
  10. # ** Note: Tom Phelps does no longer maintain the code        **
  11. # ** Bugs: to ach@rosat.mpe-garching.mpg.de (Achim Bohnet)    **
  12. # **       or exmh-workers@parc.xerox.com (EXMH mailing list)    **
  13. #    
  14. # 29-Dec-94, 2pm-7pm  &  30-Dec-94, 2:30pm-4pm
  15. # 20-Feb    don't recursively index subfolders (Achim Bohnet)
  16. # 22-Feb     Preferences support and Glimpse_Index could be run in background (ach)
  17. # 23-Feb    subfolder search mode added (ach)
  18. #
  19. # 03-Jan-97     max # of messages limit (Vinnie Shelton)
  20. # 03-Feb-97     pattersn that begin with - (?)
  21. # 11-Feb-97     bug fix and more strict folder pattern (Kazuro Furukawa)
  22. # 13-Jul-97     version info, tested with V2.1/V4.0 (Kazuro Furukawa)
  23. #
  24. # bugs:
  25. #    glimpseindex could be executed more than once.
  26. #
  27. # features:
  28. #    glimpse indexing of folders
  29. #    glimpse searching of folders, with hypertext links from match list to matches
  30. #    selected glimpse options available from pulldown menu
  31. #
  32.  
  33. #    Before searching files, you need to index them with the glimpseindex
  34. #    button.  Click all to iterate over all folders (both searching and indexing).
  35. #    From a list of matches, click on the blue identifier to jump directly
  36. #    to that message and highlight for the first match of the pattern.
  37. #    Read the glimpse(1) manual page for more information.
  38.  
  39. #  glimpse options used in glimpse.tcl        : version   : variable
  40. #
  41. #  -H : index directory                : since 1.0:always
  42. #  -y : do not prompt                : since 1.0:always
  43. #  -# : approximate matching (max error in match):since 1.0:glimpse(maxerr)
  44. #  -B : approximate matching (best match)    : since 1.0:glimpse(maxerr)
  45. #  -w : whole word                : since 1.0:glimpse(word)
  46. #  -i : case insensitive            : since 1.0:glimpse(caseSen)
  47. #  -F : file pattern                : since 1.0:glimpse(singleIndex)
  48. #  -W : AND scope whole file            : since 2.0:glimpse(andscope)
  49. #  -L {limit} : limit on the matches        : since 2.0:glimpse(maxhits)
  50. #               (max hits (per folder))
  51. #  -L {limit}:0:{flimit} : limit per file    : since 3.0:glimpse(maxhitsMsg)
  52. #               (max hits per message)
  53.  
  54. # Glimpse_Init has been moved to extrasInit.tcl
  55.  
  56. proc Glimpse_Startup {} {
  57. # tmp: no need for $exwin when 'text' is replaced by 'Widget_Text'
  58.     global glimpse exwin
  59.  
  60.     if ![info exists glimpse(init)] {
  61.     Exmh_Status "Glimpse not initialized" error
  62.     return
  63.     }
  64.     # set default variable values
  65.     set glimpse(search) ""
  66.     set glimpse(andscope) ""
  67.     set glimpse(giall) 0
  68.  
  69.     if {$glimpse(maxErrors) == "none"} {
  70.     set glimpse(maxerr) " "
  71.     } else {
  72.     set glimpse(maxerr) "-$glimpse(maxErrors)"
  73.     }
  74.     if $glimpse(caseSensitive) {
  75.     set glimpse(caseSen) ""
  76.     } else {
  77.     set glimpse(caseSen) "-i"
  78.     }
  79.     if $glimpse(wholeWord) {
  80.     set glimpse(word) "-w"
  81.     } else {
  82.     set glimpse(word) ""
  83.     }
  84.     set glimpse(searchrng) $glimpse(searchRange)
  85.  
  86.     # Current prefs are set exit if glimpse window exits
  87.     set w .glimpse
  88.     if ![Exwin_Toplevel $w "Full Text Searching with Glimpse" Glimpse] {
  89.     # Interface already initialized
  90.     return
  91.     }
  92.  
  93.     # build the gui
  94.     wm minsize $w 200 200
  95.     wm iconname $w "exmh Glimpse"
  96.  
  97.     # info, glimpseindex, dismiss
  98.     set f $w.but
  99.     pack $f.quit -side right -padx 2 -fill y    ;# Tweak to match
  100.     Widget_AddBut $f gui "UNindex" Glimpse_Unindex    {right padx 2 filly}
  101.     Widget_AddBut $f gi "index" Glimpse_Index         {right padx 2 filly}
  102.     Widget_CheckBut $f all "All" glimpse(giall)        {right padx 2 filly}
  103.     Widget_Label $f info {top fillx} -textvariable glimpse(info) -anchor w
  104.  
  105.     set glimpse(giall) 1
  106.  
  107.     # glimpse
  108.     set f [Widget_Frame $w g Menubar {top fillx}]
  109.     Widget_AddBut $f glimpse "Search" Glimpse_Search    {left padx 2 filly}
  110.     set glimpse(searchButton) $f.glimpse
  111.     $f.glimpse config -width 6
  112.     set m [Widget_AddMenuB $f opts "Opts..."         {left padx 2 filly}]
  113.     Widget_CheckMenuItem $m "case sensitive" {} glimpse(caseSen) \
  114.              -onvalue "" -offvalue "-i"
  115.     if {$glimpse(version) >= 2.0} {
  116.     if $glimpse(singleIndex) {
  117.         set title "max hits"
  118.     } else {
  119.         set title "max hits per folder"
  120.     }
  121.     set m2 [Widget_CascadeMenuItem $m $title {} m2]
  122.     set glimpse(maxhits)   $glimpse(maxHits)
  123.     foreach i {10 50 100 200 500 1000 2000 10000} {
  124.         Widget_RadioMenuItem $m2 $i {} glimpse(maxhits) $i
  125.     }
  126.     }
  127.     if {$glimpse(version) >= 3.0} {
  128.     set m2 [Widget_CascadeMenuItem $m "max hits per message" {} m3]
  129.     set glimpse(maxhitsMsg) $glimpse(maxHitsMsg)
  130.     if {$glimpse(maxhitsMsg) == "unlimited"} {
  131.         set glimpse(maxhitsMsg) 0
  132.     }
  133.     Widget_RadioMenuItem $m2 unlimited {} glimpse(maxhitsMsg) 0
  134.     foreach i {1 5 10 100} {
  135.         Widget_RadioMenuItem $m2 $i {} glimpse(maxhitsMsg)
  136.     }
  137.     }
  138.     set m2 [Widget_CascadeMenuItem $m "max errors in match" {} m4]
  139.     Widget_RadioMenuItem $m2 none {} glimpse(maxerr) " "
  140.     foreach i {1 2 3 4 5 6 7 8} {
  141.     Widget_RadioMenuItem $m2 $i {} glimpse(maxerr) -$i
  142.     }
  143. # best match doesn't work very well (weird output)
  144.     Widget_RadioMenuItem $m2 best {} glimpse(maxerr) -B
  145.  
  146.     Widget_CheckMenuItem $m "match whole word" {} glimpse(word) \
  147.                 -onvalue "-w" -offvalue ""
  148. # AND scope buggy?
  149.     if {$glimpse(version) >= 2.0} {
  150.     Widget_CheckMenuItem $m "AND scope whole file" {} glimpse(andscope) \
  151.                 -onvalue "-W" -offvalue ""
  152.     } else {
  153.     set glimpse(andscope) ""
  154.     }
  155.     Widget_Entry $f e {left fillx expand padx 2}  -textvariable glimpse(search)
  156.     Widget_BindEntryCmd $f.e <Key-Return> "$f.glimpse invoke"
  157.     Widget_RadioBut $f all "all" glimpse(searchrng)
  158.     Widget_RadioBut $f sub "subtree" glimpse(searchrng)
  159.     Widget_RadioBut $f cur "current" glimpse(searchrng)
  160.  
  161.     # results list
  162.     Widget_Frame $w results
  163.     set t [Widget_Text $w.results 20 \
  164.         -relief raised -borderwidth 2]
  165.     # Set up tag for hyper link
  166.     if {[winfo depth .] > 4} {
  167.     # Colors as in Mosaic: blue3 and ?violetred3?
  168.         Preferences_Resource glimpse(anchorColor) anchorColor blue
  169.         Preferences_Resource glimpse(visitedAnchorColor) visitedAnchorColor "violet red"
  170.     set glimpse(hyper) [list -underline 1 -foreground $glimpse(anchorColor)]
  171.     set glimpse(hyperUsed) [list -foreground $glimpse(visitedAnchorColor)]
  172.     } else {
  173.     set fg [option get $t foreground Foreground]
  174.     set bg [option get $t background Background]
  175.     set glimpse(hyper) [list -foreground $bg -background $fg]
  176.     set glimpse(hyperUsed) $glimpse(hyper)
  177.     }
  178.     append glimpse(hyper) " -lmargin2 1i"    ;# wrap indent
  179.     append glimpse(hyperUsed) " -lmargin2 1i"    ;# wrap indent
  180.     $t tag configure indent -lmargin2 10m -lmargin1 5m
  181.     eval {$t tag configure hyper} $glimpse(hyper)
  182.     eval {$t tag configure hyperUsed} $glimpse(hyperUsed)
  183.     $t tag bind hyper <ButtonRelease-1> {
  184.     Glimpse_Hyper [%W get "@%x,%y linestart" "@%x,%y lineend"]
  185.     Glimpse_HyperUsed %W @%x,%y
  186.     }
  187.     $t tag bind hyperUsed <ButtonRelease-1> {
  188.     Glimpse_Hyper [%W get "@%x,%y linestart" "@%x,%y lineend"]
  189.     }
  190.     $t tag bind hyper <Enter> {set glimpse(cursor) [lindex [%W config -cursor] 4] ; %W config -cursor tcross}
  191.     $t tag bind hyperUsed <Enter> {set glimpse(cursor) [lindex [%W config -cursor] 4] ; %W config -cursor tcross}
  192.     $t tag bind hyper <Leave> {%W config -cursor $glimpse(cursor)}
  193.     $t tag bind hyperUsed <Leave> {%W config -cursor $glimpse(cursor)}
  194.  
  195.     bind $t <Destroy> {catch unset glimpse(results)}
  196.     set glimpse(results) $t
  197. }
  198.  
  199.  
  200.  
  201. proc Glimpse_Search {} {
  202.     global glimpse mhProfile flist exmh env
  203.  
  204.     if [regexp -- "^\[     \]*\$" $glimpse(search)] {
  205.     set glimpse(info) "Empty search string specified"
  206.     bell
  207.     return
  208.     }
  209.     set state [$glimpse(searchButton) cget -text]
  210.     if {$state == "Stop"} {
  211.     # search already in progress
  212.     Glimpse_Stop
  213.     } else {
  214.        after 1 Glimpse_Start
  215.    }
  216. }
  217. proc Glimpse_Stop {} {
  218.     global glimpse
  219.     catch {set pid [pid $glimpse(channel)]}
  220.     catch {close $glimpse(channel)}
  221.     catch {exec kill $pid}
  222.     set glimpse(stop) 1
  223.     set glimpse(eof) 1
  224.     $glimpse(searchButton) config -text Search -command Glimpse_Search
  225. }
  226. proc Glimpse_Start {} {
  227.     global glimpse mhProfile flist exmh env
  228.     set glimpse(stop) 0
  229.     $glimpse(searchButton) config -text Stop -command Glimpse_Stop
  230.  
  231.     set t $glimpse(results)
  232.     set zname1 {\((.+)\)$}
  233.     set zname2 {"?([^"]+)"? <[^>]+>$}
  234.     set zdate {([0-9]+.(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec).[0-9]+)}
  235.     set me $env(USER)
  236.  
  237.     $t configure -state normal
  238.     $t delete 1.0 end
  239.     $t mark set insert 1.0
  240.     $t configure -state disabled
  241.     if {$glimpse(searchrng) == "current"} {
  242.     set folders $exmh(folder)
  243.     } else {
  244.     # all or subtree (checked inside loop)
  245.     set folders $flist(allfolders)
  246.     }
  247.  
  248.     if {$glimpse(version) >= 3.0} {
  249.     set opts "-y -L $glimpse(maxhits):0:$glimpse(maxhitsMsg) $glimpse(caseSen) $glimpse(maxerr) $glimpse(word) $glimpse(andscope)"
  250.     } else {if {$glimpse(version) >= 2.0} {
  251.     set opts "-y -L $glimpse(maxhits) $glimpse(caseSen) $glimpse(maxerr) $glimpse(word) $glimpse(andscope)"
  252.     } else {
  253.     set opts "-y $glimpse(caseSen) $glimpse(maxerr) $glimpse(word)"
  254.     } }
  255.  
  256.     set cnt 0
  257.     if $glimpse(singleIndex) {
  258.     set folders "."
  259.     # If searching all, no need to append any options.  Otherwise,
  260.     # restrict search to part of the tree
  261.     if {$glimpse(searchrng) == "subtree"} {
  262.         # append opts "-F /$exmh(folder)/"
  263.         set optf $mhProfile(path)/$exmh(folder)
  264.         set optfl [string length $optf]
  265.         set optf [string range $optf [expr $optfl - 32] [expr $optfl - 1]]
  266.         append opts " -F $optf"
  267.     } elseif {$glimpse(searchrng) == "current"} {
  268.         # append opts "-F /$exmh(folder)/\[0-9\]+$"
  269.         set optf $mhProfile(path)/$exmh(folder)/\[0-9\]*$
  270.         set optfl [string length $optf]
  271.         set optf [string range $optf [expr $optfl - 32] [expr $optfl - 1]]
  272.         append opts " -F $optf"
  273.     }
  274.     }
  275.     foreach f $folders {
  276.     if {$glimpse(stop)} {
  277.         break
  278.     }
  279.     if {(! $glimpse(singleIndex)) && $glimpse(searchrng) == "subtree"} {
  280.         if ![regexp -- $exmh(folder).* $f] {
  281.         continue
  282.         }
  283.     }
  284.     if $glimpse(singleIndex) {
  285.         set glimpse(info) "Searching..."
  286.     } else {
  287.         set glimpse(info) "Searching $f..."
  288.     }
  289.     set dir $mhProfile(path)/$f
  290.     set idir $mhProfile(path)/.glimpse/$f
  291.     catch {unset gtmp}
  292.  
  293.     if {![file readable $idir/.glimpse_index]} {
  294.         GlimpseLog $t "$f: (no glimpse index)\n"
  295.         continue
  296.     }
  297.  
  298.     set lastnum -1
  299.     Exmh_Debug $glimpse(path)/glimpse $opts -H $idir -e $glimpse(search)
  300.     if [catch {
  301.         open "| $glimpse(path)/glimpse $opts -H $idir -e \"$glimpse(search)\"" r
  302.     } x] {
  303.         Exmh_Debug $x
  304.         set result $x
  305.     } else {
  306.         set glimpse(result) {}
  307.         fileevent $x readable [list GlimpseRead $x]
  308.         set glimpse(channel) $x
  309.         tkwait variable glimpse(eof)
  310.         set result $glimpse(result)
  311.     }
  312.     $t configure -state normal
  313.     set mhresult {}
  314.  
  315.     if $glimpse(singleIndex) {
  316.         catch {unset dirlist}
  317.         set msgSrch $mhProfile(path)
  318.         append msgSrch {/*([^ ]+)/([0-9]+): (.*)}
  319.         foreach r [split $result "\n"] {
  320.         if [regexp -- $msgSrch $r all curf num context] {
  321.             if {[lsearch -exact $mhresult $curf]==-1} {
  322.             lappend mhresult $curf
  323.             }
  324.             if {![info exists dirlist($curf)]} {
  325.             set dirlist($curf) {}
  326.             }
  327.             if {[lsearch -exact $dirlist($curf) $num] == -1} {
  328.             lappend dirlist($curf) $num
  329.             }
  330.             lappend gtmp($curf/$num) $context
  331.         }
  332.         }
  333.         set dolist {}
  334.         # Sort the list of directories by name.  For each directory,
  335.         # sort the messages by number.
  336.         foreach msgdir [lsort -ascii $mhresult] {
  337.         foreach n [lsort -integer $dirlist($msgdir)] {
  338.             lappend dolist $msgdir/$n
  339.         }
  340.         }
  341.     } else {
  342.         # collect all matches to MH messages
  343.         # (two pass process in order to sort by message number)
  344.         foreach r [split $result "\n"] {
  345.         if [regexp -- {/[^ ]+/([0-9]+): (.*)} $r all num context] {
  346.             if {[lsearch -exact $mhresult $num]==-1} {
  347.             lappend mhresult $num
  348.             }
  349.             # this is a local array, so it goes away
  350.             # after this proc is done
  351.             lappend gtmp($num) $context
  352.         }
  353.         }
  354.         set dolist [lsort -integer $mhresult]
  355.     }
  356.     foreach r $dolist {
  357.         set num $r; set context $gtmp($num)
  358.  
  359.         if {$num!=$lastnum} {
  360.         incr cnt
  361.         set lastnum $num
  362.         if $glimpse(singleIndex) {
  363.             set file $mhProfile(path)/$num
  364.             $t insert end "$num"
  365.         } else {
  366.             set file $dir/$num
  367.             $t insert end "$f/$num"
  368.         }
  369.         $t insert end " "
  370.         $t tag add hyper "insert linestart" "insert lineend -1c"
  371.  
  372.         ## grab some header fields
  373.         if [file readable $file] {
  374.             set from ""; set to ""; set subject ""; set date ""
  375.  
  376.             set fid [open $file]
  377.             while {[gets $fid line]!=-1} {
  378.             if {$line==""} break
  379.             if {[regexp -nocase "^(from|to|subject|date): *(.*)" $line all field match]} {
  380.                 set [string tolower $field] $match
  381.             }
  382.             }
  383.  
  384.             ## post processing of fields
  385.  
  386.             # From => To if me; chop e-mail
  387.             set pfx ""
  388.             if {[string match "*$me*" $from]} {set from $to; set pfx "to:"}
  389.             # blind carbon copy?
  390.             if {$from==""&&$to==""&&[gets $fid line]!=-1 && [string match "*Blind-Carbon-Copy*" $line]} {
  391.             gets $fid; # gobble blank line
  392.             while {[gets $fid line]!=-1 && $line!=""} {
  393.                 if {[regexp {^To: (.*)} $line all match]} {
  394.                 set from $match
  395.                 break
  396.                 }
  397.             }
  398.             }
  399.             if {[regexp $zname1 $from all match]} {set from $match} \
  400.             elseif {[regexp $zname2 $from all match]} {set from $match}
  401.             set from "$pfx$from"
  402.  
  403.             # Date => day-mon-year
  404.             if {[regexp -nocase $zdate $date all match]} {set date $match}
  405.  
  406.             # Subject (no change)
  407.  
  408.             set start [$t index insert]
  409.             $t insert end "$from / $date / $subject\n"
  410.             $t tag add indent $start insert
  411.             catch {close $fid}
  412.         }
  413.         }
  414.         foreach c $context {
  415.         set start [$t index insert]
  416.         $t insert end "$c\n"
  417.         $t tag add indent $start insert
  418.         }
  419.     }
  420.     $t configure -state disabled
  421.     $t see end
  422.     }
  423.     $glimpse(searchButton) config -text Search -command Glimpse_Search
  424.  
  425.     switch -- $cnt {
  426.     0    {set match "no matches"}
  427.     1    {set match "1 match"}
  428.     default {set match "$cnt matches"}
  429.     }
  430.     set glimpse(info) "Searching completed, $match"
  431.     $t yview 1.0
  432. }
  433. proc GlimpseRead {in} {
  434.     global glimpse
  435.     if [eof $in] {
  436.     catch {close $in}
  437.     set glimpse(eof) 1
  438.     } else {
  439.     append glimpse(result) [gets $in]\n
  440.     }
  441. }
  442. proc Glimpse_HyperUsed {t idx} {
  443.     set range [$t tag nextrange hyper "$idx linestart" "$idx lineend"]
  444.     if {"x$range" == "x"} {
  445.     return
  446.     }
  447.     eval $t tag remove hyper $range
  448.     eval $t tag add hyperUsed $range
  449. }
  450.  
  451. proc Glimpse_Hyper {hyper} {
  452.     global glimpse exmh
  453.  
  454.     if {![regexp {([^ ]+)/([0-9]+)} $hyper all folder msg]} return
  455.  
  456.     # show message
  457.     if {[string compare $folder $exmh(folder)] != 0} {
  458.     Folder_Change $folder [list Msg_Change $msg]
  459.     } else {
  460.     Msg_Change $msg
  461.     }
  462.  
  463.     # show (first) search string within message
  464.     # (save old values of choice, entry?)
  465.     regsub -all -- {;|,} $glimpse(search) "|" search
  466.  
  467.     Find_Setup
  468.     global glimpse find
  469.     set find(choice) "Msg"
  470.     # find(entry) should use a textvariable
  471.     $find(entry) delete 0 end; $find(entry) insert 0 $search
  472.     Find_It
  473. }
  474.  
  475. proc Glimpse_Index { } {
  476.     global glimpse mhProfile flist exmh
  477.  
  478.     #Glimpse toplevel never created
  479.     if [info exists glimpse(results)] {
  480.     set t $glimpse(results)
  481.     $t configure -state normal
  482.     $t delete 1.0 end
  483.     $t mark set insert 1.0
  484.     $t configure -state disabled
  485.     }
  486.  
  487.     if ![file isdirectory $mhProfile(path)/.glimpse] {
  488.     if [catch {exec mkdir $mhProfile(path)/.glimpse} err] {
  489.         set glimpse(info) $err
  490.         return
  491.     }
  492.     }
  493.  
  494.     if {! $glimpse(singleIndex)} {
  495.     set folders [expr {$glimpse(giall)?"$flist(allfolders)":"$exmh(folder)"}]
  496.  
  497.     # only update if out of date
  498.     set i 0
  499.     # Put glimpse indexes into an alternate directory structure
  500.     # so modifications to the glimpse files do not bother exmh
  501.     foreach f $folders {
  502.         set dir $mhProfile(path)/$f
  503.         set idir $mhProfile(path)/.glimpse/$f
  504.         if ![file exists $dir] {
  505.         # Folder gone
  506.         File_Delete $idir
  507.         continue
  508.         }
  509.         set gf $idir/.glimpse_filenames
  510.         if [catch {MakeDir $idir} err] {
  511.         continue
  512.         } elseif {![file writable $idir]} {
  513.         set rmsg "$f: $idir not writable"
  514.         continue
  515.         }
  516.         if ![file exists $gf] {
  517.         set index full
  518.         set glimpse(info) "Indexing $f..."
  519.         } elseif {[file mtime $dir]>[file mtime $gf]} {
  520.         #set index update
  521.         # Incremental seems broken (infinite loop) and
  522.         # does not handle deleted files properly, so
  523.         set index full
  524.         set glimpse(info) "Updating index for $f..."
  525.         } else {
  526.         # index still current
  527.         set glimpse(info) "Index for '$f' still current"
  528.         update idletasks
  529.         continue
  530.         }
  531.         update idletasks
  532.         # exclude subdirectories (want no-recursive switch), but...
  533.         # collect subdirectories of current directory
  534.         set subdirs {}
  535.         foreach sub $folders {
  536.         if [string match $f/* $sub] {lappend subdirs $sub}
  537.         }
  538.  
  539.         # don't index deleted files (.*) or subdirectories
  540.         set fid [open "$idir/.glimpse_exclude" "w"]
  541.         puts $fid "*/.*"
  542.         puts $fid "*/$mhProfile(delprefix)*"
  543.         puts $fid "*/*~"
  544.         foreach sub $subdirs { puts $fid "*/[file tail $sub]" }
  545.         close $fid
  546.  
  547.         Exmh_Status "Indexing $f..."
  548.         update idletasks
  549.         set r [Glimpse_Batch $i\
  550.             [list $glimpse(path)/glimpseindex -H $idir $dir]]
  551.         incr i
  552.         if ![file exists $idir/.glimpse_index] {
  553.         set rmsg "$f index failed"
  554.         continue
  555.         }
  556.         if ![file exists $idir/.glimpse_filenames] {
  557.         set rmsg "$f has no files"
  558.         continue
  559.         }
  560.         set rl [split $r "\n"]
  561.         if {[set ix [lsearch -regexp $rl "^Size"]]!=-1} {
  562.         regexp -- {.*= ([0-9]+) B.* = ([0-9]+)$} \
  563.             [lindex $rl $ix] all bytes files
  564.         set isize [expr \
  565.             {[file size $idir/.glimpse_index] + \
  566.             [file size $idir/.glimpse_filenames]}]
  567.         if {$bytes > 0} {
  568.             set overhead [expr 100.0 * $isize / $bytes]
  569.         } else {
  570.             set overhead 0
  571.         }
  572.         set rmsg [format \
  573.             "%-20s %5d files, %8d bytes, %7d index bytes, %%%.1f" \
  574.             $f $files $bytes $isize $overhead]
  575.         } else {
  576.         set rmsg $r
  577.         }
  578.         # status message (check if glimpse window was already created)
  579.         if [info exists glimpse(results)] {
  580.         GlimpseLog $t $rmsg\n
  581.         }
  582.     }
  583.     } else {
  584.     set gdir $mhProfile(path)/.glimpse
  585.     # If .glimpse_exclude doesn't exist, create a default version...
  586.     if ![file exists "$gdir/.glimpse_exclude"] {
  587.         set fid [open "$gdir/.glimpse_exclude" "w"]
  588.         puts $fid "*/.*"
  589.         puts $fid "*/$mhProfile(delprefix)*"
  590.         puts $fid "*/*~"
  591.         close $fid
  592.     }
  593.     Exmh_Status "Indexing all mail..."
  594.     set glimpse(info) "Indexing all mail..."
  595.     update idletasks
  596.     Exmh_Debug $glimpse(path)/glimpseindex -H $gdir $mhProfile(path)
  597.     set r [Glimpse_Batch 0 [list $glimpse(path)/glimpseindex \
  598.         -H $gdir $mhProfile(path)]]
  599.     if ![file exists $gdir/.glimpse_index] {
  600.         set rmsg "Index failed!"
  601.     } elseif ![file exists $gdir/.glimpse_filenames] {
  602.         set rmsg "No mail to index!"
  603.     } else {
  604.         set rl [split $r "\n"]
  605.         if {[set ix [lsearch -regexp $rl "^Size"]]!=-1} {
  606.         regexp -- {.*= ([0-9]+) B.* = ([0-9]+)$} \
  607.             [lindex $rl $ix] all bytes files
  608.         set isize [expr \
  609.             {[file size $gdir/.glimpse_index] + \
  610.             [file size $gdir/.glimpse_filenames]}]
  611.         if {$bytes > 0} {
  612.             set overhead [expr 100.0 * $isize / $bytes]
  613.         } else {
  614.             set overhead 0
  615.         }
  616.         set rmsg [format \
  617.             "%5d files, %8d bytes, %7d index bytes, %%%.1f" \
  618.             $files $bytes $isize $overhead]
  619.         } else {
  620.         set rmsg $r
  621.         }
  622.     }
  623.     # status message (check if glimpse window was already created)
  624.     if [info exists glimpse(results)] {
  625.         GlimpseLog $t $rmsg\n
  626.     }
  627.     }
  628.  
  629.     set glimpse(info) "Indexing completed"
  630.     if [info exists t] {
  631.     $t see 1.0
  632.     }
  633. }
  634. proc MakeDir { path } {
  635.     if [file isdirectory $path] {
  636.     return
  637.     } else {
  638.     if ![file isdirectory [file dirname $path]] {
  639.         MakeDir [file dirname $path]
  640.     }
  641.     exec mkdir $path
  642.     }
  643. }
  644.  
  645. proc Glimpse_Batch { i cmd } {
  646.     global glimpse wish exmh
  647.  
  648.     if !$exmh(bgAsync) {
  649.         # For UNSECURE X-servers
  650.     catch {eval exec $cmd} out
  651.     Glimpse_BatchDone "$out"
  652.     set glimpse(done) $out
  653.     update idletask
  654.     } else {
  655.         # For working 'send' (SECURE X-servers)
  656.     set path [Env_Tmp]/glimpse.[pid].$i
  657.     if [catch {open $path w} out] {
  658.     Exmh_Status "$path $out"
  659.     return
  660.     }
  661.     puts $out "wm withdraw ."
  662.     set myname [winfo name .]
  663.     puts $out "catch \{exec $cmd\} out"
  664.     puts $out "catch \{send [list $myname] \[list Glimpse_BatchDone \$out\]\}"
  665.     puts $out "exec rm $path"
  666.     puts $out exit
  667.     close $out
  668.     set glimpse(done) {}
  669.     exec $wish -f $path &
  670.     tkwait var glimpse(done)
  671.     }
  672.     return $glimpse(done)
  673. }
  674.  
  675. proc Glimpse_BatchDone { out } {
  676.     global glimpse
  677.     Exmh_Status "Glimpse_BatchDone $out"
  678.     set glimpse(done) $out
  679. }
  680.  
  681.  
  682. proc Glimpse_Unindex {} {
  683.     global glimpse mhProfile flist exmh
  684.  
  685.     set t $glimpse(results)
  686.     $t configure -state normal
  687.     $t delete 1.0 end
  688.     $t mark set insert 1.0
  689.     $t configure -state disabled
  690.     if {! $glimpse(singleIndex)} {
  691.     set folders [expr {$glimpse(giall)?"$flist(allfolders)":"$exmh(folder)"}]
  692.     } else {
  693.     set folders "."
  694.     }
  695.  
  696.     foreach f $folders {
  697.     set glimpse(info) "Unindex $f..."
  698.     update idletasks
  699.     set rmsg [Glimpse_Delete $f]
  700.     GlimpseLog $t $rmsg\n
  701.     }
  702.  
  703.     set glimpse(info) "Unindexing completed"
  704.     $t see 1.0
  705. }
  706. proc Glimpse_Delete { f } {
  707.     global glimpse mhProfile
  708.     set idir $mhProfile(path)/.glimpse/$f
  709.     set gf $idir/.glimpse_filenames
  710.     set rmsg "$f: "
  711.  
  712.     if {![file writable $idir]} {
  713.     append rmsg "$idir not writable"
  714.     } elseif {![file exists $gf]} {
  715.     append rmsg "(no glimpse index files)"
  716.     } else {
  717.     if {[catch {eval File_Delete [glob "$idir/.glimpse_*"]} info]} {
  718.         append rmsg "$info"
  719.     } else {
  720.         append rmsg "glimpse index files deleted"
  721.         catch {exec rmdir $idir}
  722.     }
  723.     }
  724.     return $rmsg
  725. }
  726. proc GlimpseLog {t string} {
  727.     $t config -state normal
  728.     $t insert end $string
  729.     $t see end
  730.     $t config -state disabled
  731.     update idletasks
  732. }
  733.